#include "stdafx.h"
#include "net/HTTPHeaderStream.hpp"

NET_NAMESPACE_BEGIN

//
// CHTTPHeaderStreamBuf
//
CHTTPHeaderStreamBuf::CHTTPHeaderStreamBuf(CHTTPSession& session, openmode mode)
	: HTTPBasicStreamBuf(CHTTPBufferAllocator::BUFFER_SIZE, mode),
	m_session(session),
	m_end(false)
{
}

CHTTPHeaderStreamBuf::~CHTTPHeaderStreamBuf()
{
}

int CHTTPHeaderStreamBuf::readFromDevice(char* buffer, std::streamsize length)
{
	// read line-by-line; an empty line denotes the end of the headers.
	static const int eof = std::char_traits<char>::eof();

	if (m_end)
		return 0;

	int n = 0;
	int ch = m_session.get();
	while (ch != eof && ch != '\n' && n < length - 1)
	{
		*buffer++ = (char) ch; ++n;
		ch = m_session.get();
	}
	if (ch != eof)
	{
		*buffer++ = (char) ch; ++n;
		if (n == 2) 
			m_end = true;
	}
	return n;
}

int CHTTPHeaderStreamBuf::writeToDevice(const char* buffer, std::streamsize length)
{
	return m_session.write(buffer, length);
}


//
// CHTTPHeaderIOS
//
CHTTPHeaderIOS::CHTTPHeaderIOS(CHTTPSession& session, CHTTPHeaderStreamBuf::openmode mode) : m_buf(session, mode)
{
	
}

CHTTPHeaderIOS::~CHTTPHeaderIOS()
{
	try
	{
		m_buf.sync();
	}
	catch (...)
	{
	}
}

CHTTPHeaderStreamBuf* CHTTPHeaderIOS::rdbuf()
{
	return &m_buf;
}


//
// CHTTPHeaderInputStream
//
CMemoryPool CHTTPHeaderInputStream::m_pool(sizeof(CHTTPHeaderInputStream));

CHTTPHeaderInputStream::CHTTPHeaderInputStream(CHTTPSession& session) 
	: CHTTPHeaderIOS(session, std::ios::in),
	std::istream(&m_buf)
{
}

CHTTPHeaderInputStream::~CHTTPHeaderInputStream()
{
}

void* CHTTPHeaderInputStream::operator new(std::size_t size)
{
	return m_pool.get();
}

void CHTTPHeaderInputStream::operator delete(void* ptr)
{
	try
	{
		m_pool.release(ptr);
	}
	catch (...)
	{
		jh_unexpected();
	}
}


//
// CHTTPHeaderOutputStream
//
CMemoryPool CHTTPHeaderOutputStream::m_pool(sizeof(CHTTPHeaderOutputStream));

CHTTPHeaderOutputStream::CHTTPHeaderOutputStream(CHTTPSession& session)
	: CHTTPHeaderIOS(session, std::ios::out),
	std::ostream(&m_buf)
{
}

CHTTPHeaderOutputStream::~CHTTPHeaderOutputStream()
{
}

void* CHTTPHeaderOutputStream::operator new(std::size_t size)
{
	return m_pool.get();
}

void CHTTPHeaderOutputStream::operator delete(void* ptr)
{
	try
	{
		m_pool.release(ptr);
	}
	catch (...)
	{
		jh_unexpected();
	}
}

NET_NAMESPACE_END
